﻿//////////////////////////////////////////////////////////////////
//
// ILocation.cs
//
// Copyright (c) 2012 Dan Pike.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Interfaces
{
   ////////////////////////////////////////////////////////////////////////
   /// <summary>
   ///
   /// </summary>
   public enum Hemisphere
   {
      None,
      North,
      South,
      East,
      West
   }

   ////////////////////////////////////////////////////////////////////////
   /// <summary>
   ///
   /// </summary>
   public enum Compass
   {
      None,
      East,
      NorthEast,
      North,
      NorthWest,
      West,
      SouthWest,
      South,
      SouthEast,
   }

   ////////////////////////////////////////////////////////////////////////
   /// <summary>
   /// Represents a single point on an ITerrain. Terrains are to a resolution
   /// of one arc-second (equivalent to about 30m on the Earth's surface).
   /// It's more efficient to store them in 4-byte integer arc seconds rather than
   /// real numbers of radians.
   /// 
   /// The values are modulo 1296000 == 360 degrees x 3600 seconds-per-degree
   /// </summary>
   [TypeConverter(typeof(ConverterILocation))]
   public interface ILocation
   {
      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Initialize the object from a string, which should be in the same
      /// format as produced that by ToString()
      /// </summary>
      /// <param name="format">e.g. "[N.50.4.15, E.14.55.6]"</param>
      /// <returns>this</returns>
      ILocation FromString(string format);

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Create a copy of this instance
      /// </summary>
      /// <returns>this</returns>
      ILocation Clone();

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Move in the given direction without changing altitude
      /// </summary>
      /// <param name="latitudeOffset"></param>
      /// <param name="longitudeOffset"></param>
      /// <returns>this</returns>
      ILocation Move(float latitudeOffset, float longitudeOffset);

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Move in the given direction and adjust the hemisphere etc if we
      /// cross a significant boundary.
      /// Equator is at 0 degrees North, date line is at 180 degrees East
      /// </summary>
      /// <param name="latitudeOffset"></param>
      /// <param name="longitudeOffset"></param>
      /// <param name="altitudeChange"></param>
      /// <returns>this</returns>
      ILocation Move(float latitudeOffset, float longitudeOffset, float altitudeChange);

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Set equal to the position given by the src location
      /// </summary>
      /// <param name="src"></param>
      /// <returns>this</returns>
      ILocation CopyFrom(ILocation src);

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Overall longitude (in arc-seconds) for this location
      /// </summary>
      float Longitude { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Either Hemisphere.West or Hemisphere.East
      /// </summary>
      Hemisphere LongitudeHemisphere { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-degrees component of the longitude, excluding hemisphere
      /// (zero or positive)
      /// </summary>
      int LongitudeDegrees { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-minutes component of the longitude, excluding degrees
      /// </summary>
      int LongitudeMinutes { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-minutes component of the longitude, including hemisphere and
      /// degrees as a signed quantity
      /// </summary>
      int LongitudeTotalMinutes { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The seconds component of the longitude, excluding hemisphere
      /// degrees and minutes (zero or positive)
      /// </summary>
      float LongitudeSeconds { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Overall latitude (in arc-seconds) for this location
      /// </summary>
      /// <returns></returns>
      float Latitude { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Either Hemisphere.North or Hemisphere.South
      /// </summary>
      Hemisphere LatitudeHemisphere { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-degrees component of the latitude, excluding hemisphere
      /// (zero or positive)
      /// </summary>
      int LatitudeDegrees { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-minutes component of the latitude, excluding degrees
      /// </summary>
      int LatitudeMinutes { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The whole-minutes component of the latitude, including hemisphere and
      /// degrees as a signed quantity
      /// </summary>
      int LatitudeTotalMinutes { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// The seconds component of the latitude, excluding hemisphere
      /// degrees and minutes (zero or positive)
      /// </summary>
      float LatitudeSeconds { get; set; }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// Altitude in metres
      /// </summary>
      float Altitude { get; set; }
   }
}
